#!/usr/bin/env python
# farbot vi:ts=4:sw=4:expandtab:
#
# Copyright (c) 2006-2008 Three Rings Design, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. Neither the name of the copyright owner nor the names of contributors
#    may be used to endorse or promote products derived from this software
#    without specific prior written permission.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

import getopt
import sys
import ZConfig

import farb
from farb import utils, builder, config, sysinstall, runner

class Main(object):
    """
    Implements FarBot's Main Runloop
    """
    doAllActions = True

    def usage(self):
        print >>sys.stderr, "Usage: %s [-h] [-o] [-f config file] [-r action]" % sys.argv[0]
        print >>sys.stderr, "    -h             print usage (this message)"
        print >>sys.stderr, "    -o             Do one action only.  Do not continue after <action>"
        print >>sys.stderr, "    -f <config>    Use configuration file <config>"
        print >>sys.stderr, "    -r <action>    Execute <action>"
        print >>sys.stderr, "\nSupported actions:"
        print >>sys.stderr, "    release        Build all defined releases, build all packages, and build the"
        print >>sys.stderr, "                   network installation root"
        print >>sys.stderr, "    package        Build all defined packages, and build the network"
        print >>sys.stderr, "                   installation root (requires a release build)"
        print >>sys.stderr, "    install        Build the network installation root (requires package and"
        print >>sys.stderr, "                   release builds)"

    def _doReleaseBuild(self, farbconfig):
        """
        Do a full release build
        @param farbconfig: zconfig config instance
        """
        print "Building all releases ..."
        try:
            rbr = runner.ReleaseBuildRunner(farbconfig)
            rbr.run()
            print "Release build completed."
        except runner.ReleaseBuildRunnerError, e:
            print >>sys.stderr, e
            sys.exit(1)

    def _doPackageBuild(self, farbconfig):
        """
        Do a full package build
        @param farbconfig: zconfig config instance
        """
        print "Building all packages ..."
        try:
            pbr = runner.PackageBuildRunner(farbconfig)
            pbr.run()
            print "Package build completed."
        except runner.PackageBuildRunnerError, e:
            print >>sys.stderr, e
            sys.exit(1)

    def _doNetInstallBuild(self, farbconfig):
        """
        Do a net install directory build
        @param farbconfig: zconfig config instance
        """
        print "Building network installation root ..."
        try:
            ibr = runner.NetInstallAssemblerRunner(farbconfig)
            ibr.run()
            print "Network installation root created."
        except runner.NetInstallAssemblerRunnerError, e:
            print >>sys.stderr, e
            sys.exit(1)

    def main(self):
        conf_file = None
        action = None

        try:
            opts,args = getopt.getopt(sys.argv[1:], "hof:r:")
        except getopt.GetoptError:
            self.usage()
            sys.exit(2)

        for opt,arg in opts:
            if opt == "-h":
                self.usage()
                sys.exit()
            if opt == "-f":
                conf_file = arg
            if opt == "-r":
                action = arg
            if opt == "-o":
                self.doAllActions = False

        if (conf_file == None or action == None):
            self.usage()
            sys.exit(1)

        # Load our configuration schema
        schema = ZConfig.loadSchema(farb.CONFIG_SCHEMA)
        try:
            farbconfig, handler = ZConfig.loadConfig(schema, conf_file)
            config.verifyReferences(farbconfig)
            config.verifyPackages(farbconfig)
        except ZConfig.ConfigurationError, e:
            print >>sys.stderr, "Configuration Error: %s" % e
            sys.exit(1)

        # Execute requested action
        if (action == "release"):
            self._doReleaseBuild(farbconfig)
            if (self.doAllActions):
                self._doPackageBuild(farbconfig)
                self._doNetInstallBuild(farbconfig)
        elif (action == "package"):
            self._doPackageBuild(farbconfig)
            if (self.doAllActions):
                self._doNetInstallBuild(farbconfig)
        elif (action == "install"):
            self._doNetInstallBuild(farbconfig)
        else:
            print >>sys.stderr, "Unknown action \"%s\".\n" % (action)
            self.usage()
            sys.exit(1)

        sys.exit(0)

if __name__ == "__main__":
    main = Main()
    main.main()
